package com.yonyou.cyxdms.basedata.client.service.basedata;

import com.yonyou.cyx.framework.bean.dto.base.ClientInfoDTO;
import com.yonyou.cyx.framework.compent.redis.RedisClient;
import com.yonyou.cyx.framework.util.bean.ApplicationContextHelper;
import com.yonyou.cyx.function.exception.ServiceBizException;
import com.yonyou.cyx.function.utils.common.CommonUtils;
import com.yonyou.cyx.function.utils.common.StringUtils;
import com.yonyou.cyx.function.utils.jsonserializer.JSONUtil;
import com.yonyou.cyxdms.basedata.client.constants.BaseDataCommonConstants;
import com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO;
import com.yonyou.cyxdms.basedata.client.domains.vo.DictVO;
import com.yonyou.cyxdms.basedata.client.dto.code.CodeDTO;
import com.yonyou.cyxdms.basedata.client.feign.BaseDataCommonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BaseCommonCodeServiceImpl implements BaseCommonCodeService {

    private final Logger logger = LoggerFactory.getLogger(BaseCommonSeriesServiceImpl.class);

    @Autowired
    private BaseDataCommonClient baseDataCommonClient;

    @Autowired
    private RedisClient redisClient;

    /**
     * 查询TCCODE
     *
     * @param type 类型
     * @return com.yonyou.cyxdms.basedata.client.domains.DTO.basedata.CodeVO
     * @author maxingjian
     * @since 2018/12/12
     */
    @Override
    public List<CodeVO> getCodeListByType(String type) {
        ClientInfoDTO loginInfoDto = ApplicationContextHelper.getBeanByType(ClientInfoDTO.class);
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.CODE_CACHE_TYPE, loginInfoDto.getAppId());
        Object codeData = redisClient.hget(messageFormat, type);
        if (codeData == null) {
            List<CodeVO> codeDtoResponse = invokeMethod(loginInfoDto.getAppId(), type);
            initOneValue(codeDtoResponse, loginInfoDto.getAppId());
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeDtoResponse), CodeVO.class);
        } else {
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), CodeVO.class);
        }
    }

    /**
     * 不登录通过type获取code
     *
     * @param type type
     * @return java.util.List<com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO>
     * @author renwd
     * @since 2020/1/2
     */
    @Override
    public List<CodeVO> listCodeByType(String appId, String type) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.CODE_CACHE_TYPE, appId);
        Object codeData = redisClient.hget(messageFormat, type);
        if (codeData == null) {
            List<CodeVO> codeDtoResponse = invokeMethod(appId, type);
            initOneValue(codeDtoResponse, appId);
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeDtoResponse), CodeVO.class);
        } else {
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), CodeVO.class);
        }
    }

    /**
     * 设置参数并执行sql
     *
     * @param appId
     * @param type
     * @return java.util.List<com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO>
     * @author renwd
     * @since 2020/1/2
     */
    private List<CodeVO> invokeMethod(String appId, String type) {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("appId", appId);
        dataMap.put("type", type);
        List<CodeVO> codeDtoResponse = baseDataCommonClient.queryCodeBySql(dataMap).getData();
        logger.info("feign查询TC_CODE信息:{}", codeDtoResponse);
        if (CommonUtils.isNullOrEmpty(codeDtoResponse)) {
            throw new ServiceBizException("TC_CODE为空!");
        }
        return codeDtoResponse;
    }

    /**
     * 数据放置redis
     *
     * @param codeDto
     * @author maxingjian
     * @since 2018/12/12
     */
    private void initOneValue(List<CodeVO> codeDto, String appId) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.CODE_CACHE_TYPE, appId);
        redisClient.hsetExpire(messageFormat, String.valueOf(codeDto.get(0).getType()), JSONUtil.objectToJson(codeDto), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
    }

    /**
     * 查询TCCODE
     *
     * @return com.yonyou.cyxdms.basedata.client.domains.DTO.basedata.CodeVO
     * @author maxingjian
     * @since 2018/12/12
     */
    @Override
    public List<CodeVO> getCodeList() {
        ClientInfoDTO loginInfoDto = ApplicationContextHelper.getBeanByType(ClientInfoDTO.class);
        return baseDataCommonClient.queryCode(loginInfoDto.getAppId()).getData();
    }

    /**
     * 新增code
     *
     * @param codeDTO
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author chengliang
     * @since 2019/10/16
     */
    @Override
    public Map<String, Object> insert(CodeDTO codeDTO) {
        return baseDataCommonClient.insert(codeDTO).getData();
    }

    /**
     * 修改code
     *
     * @param codeDTO
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author chengliang
     * @since 2019/10/16
     */
    @Override
    public Map<String, Object> updateCodePO(CodeDTO codeDTO) {
        return baseDataCommonClient.update(codeDTO).getData();
    }

    /**
     * 根据codeName查询codeVO
     *
     * @author ysj
     * @date 2019/10/21
     * @param name
     * @return
     */
    @Override
    public CodeVO getCodeVOByName(String name,Integer type) {
        return baseDataCommonClient.getCodeVOByName(name,type).getData();
    }

    /**
     * 根据codeId查询
     *
     * @param codeId
     * @param appId
     * @return com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO
     * @author dengqiang
     * @since 2019/11/1
     */
    @Override
    public CodeVO queryByCodeId(Long codeId, String appId) {
        Object codeDto = redisClient.hget(BaseDataCommonConstants.CODE_CACHE_CODEID,String.valueOf(codeId+appId));
        if (null == codeDto ) {
            // 查询所有数据
            loadValueIfNotExists(codeId, appId);
            Object redisCodeDto = redisClient.hget(BaseDataCommonConstants.CODE_CACHE_CODEID,String.valueOf(codeId+appId));
            if (null == redisCodeDto) {
                return null;
            }
            return JSONUtil.jsonToObj(JSONUtil.objectToJson(redisCodeDto), CodeVO.class);
        } else {
            return JSONUtil.jsonToObj(JSONUtil.objectToJson(codeDto),  CodeVO.class);
        }
    }

    /**
     * 根据appId查询所有tc_code(pc登录)
     *
     * @param
     * @return com.yonyou.cyx.framework.bean.dto.framework.RestResultResponse<java.util.List<com.yonyou.cyxdms.basedata.client.domains.vo.DictVO>>
     * @author dengqiang
     * @since 2019/11/15
     */
    @Override
    public List<DictVO> allCode() {
        return baseDataCommonClient.allCode().getData();
    }

    /**
     * 根据appId查询全部可用字典
     *
     * @author lyz
     * @date 2021/3/8
     */
    @Override
    public List<DictVO> allCodeAvailable() {
        return baseDataCommonClient.allCodeAvailable().getData();
    }

    /**
     * 查询数据
     *
     * @param codeId
     * @param appId
     * @return void
     * @author dengqiang
     * @since 2019/11/1
     */
    private void loadValueIfNotExists(Long codeId,String appId) {
        CodeVO codeResponse = baseDataCommonClient.queryByCodeId(codeId, appId).getData();
        logger.info("feign查询code信息:{}", codeResponse);

        if (!StringUtils.isNullOrEmpty(codeResponse)) {
            initOneValue(codeResponse,codeId, appId);
        }
    }

    /**
     * 将数据放置redis
     *
     * @param codeResponse
     * @param codeId
     * @param appId
     * @return void
     * @author dengqiang
     * @since 2019/11/1
     */
    private void initOneValue(CodeVO codeResponse, Long codeId, String appId) {
        redisClient.hsetExpire(BaseDataCommonConstants.CODE_CACHE_CODEID,String.valueOf(codeId+appId), JSONUtil.objectToJson(codeResponse), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
    }
    
    /**
     * 查询TCCODE
     *
     * @param type 类型
     * @return com.yonyou.cyxdms.basedata.client.domains.DTO.basedata.CodeVO
     * @author maxingjian
     * @since 2018/12/12
     */
    @Override
    public List<CodeVO> getCodeListByType(String type,String appId) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.CODE_CACHE_TYPE, appId);
        Object codeData = redisClient.hget(messageFormat, type);
        if (codeData == null) {
            List<CodeVO> codeDtoResponse = invokeMethod(appId, type);
            initOneValue(codeDtoResponse, appId);
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeDtoResponse), CodeVO.class);
        } else {
            return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), CodeVO.class);
        }
    }

}
